﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Hoguet.RTM
{
    public class TaskMetricsService : ITaskMetricsService
    {
        private readonly IRtmServiceFacade _rtmService;

        public TaskMetricsService(IRtmServiceFacade rtmService)
        {
            _rtmService = rtmService;
        }

        public IEnumerable<Metric<DateTime, double>> GetSevenDaysHoursRemaining ()
        {
            var tasks = _rtmService.GetTasks("dueBefore:\"7 days\"  NOT completed:").ToList();
            tasks.ForEach(task => task.Due = (task.Due < DateTime.Today ? DateTime.Today : task.Due.Value));
            var inner = tasks.GroupBy(task => task.Due.Value.Date)//assume task.Due exists because above query requires a due date before 7 days from now
                .Select(dateGroup => new Metric<DateTime, double>() {Context = dateGroup.Key, Value = dateGroup.Sum(task => task.HoursRemaining)});
            return Enumerable.Range(0, 7).Select(i => DateTime.Today.AddDays(i))
                //for some reason the compiler was saying I needed to specify the types b/c they couldn't be inferred...
                .GroupJoin<DateTime, Metric<DateTime, double>, DateTime, Metric<DateTime, double>>(
                     inner: inner
                     , innerKeySelector: metric => metric.Context
                     , outerKeySelector: day => day
                     , resultSelector: (day, dataSubSet) => new Metric<DateTime, double>() { Context = day, Value = dataSubSet.Sum(metric => metric.Value) }
                )
                .OrderBy(metric => metric.Context);
        }

        public IEnumerable<Metric<string, int>> GetHabits()
        {
            return _rtmService.GetTasks("dueWithin:\"7 days\"")
                .Where(task => task.Repeat.Contains("FREQ=DAILY;"))
                .Select(task => new Metric<string, int>(){Context = task.Name, Value = 0});
        }

        public IEnumerable<Metric<string, int>> GetOldest()
        {
            return _rtmService.GetTasks("NOT completed:")
                .OrderBy(task => task.DateCreated)
                .Take(10)
                .Select(
                    task =>
                    new Metric<string, int>()
                        {Context = task.Name, Value = (int) (DateTime.Now - task.DateCreated).TotalDays});
        }

        public IEnumerable<Metric<string, DateTime?>> GetTagged()
        {
            return _rtmService.GetTasks("tag:goal NOT completed:")
                .Select(task => new Metric<string, DateTime?>() {Context = task.Name, Value = task.Due});
        }
    }
   
}
